Java的反射机制

基础知识

概念

  • 反射是框架设计的灵魂。
  • 反射机制就是将类的各个组成部分封装为其他对象。

    优势

  • 可以在程序运行过程中,操作这些对象。
  • 可以解耦,提高程序的可扩展性。

Java代码的阶段

  • Java代码在计算机中经历的三个阶段
    • Source(源代码阶段)
      • Java文件被Javac编译为class文件,class文件会将成员变量、成员方法和构造方法等编译成不同的模块。
      • class文件通过 Classload类加载器 来进入和下一阶段。
    • Class(类对象阶段)
      • 通过 Classload类加载器,将class文件加载进内存,成员变量、成员方法和构造方法会被封装为Class类中的对象。
    • Runtime(运行阶段)
      • 当我们需要访问Java文件的成员时,我们就可以逆向访问,通过Class类的Classload类加载器来获取该成员的对象。

获取Class对象

  • Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。
    • 处于Source(源代码阶段),并未加载进内存。
      • 用于配置文件,将类名定义在配置文件中。读取文件,从而加载类。
  • 类名.class:通过类名的属性class获取。
    • 处于Class(类对象阶段),已经加载进内存。
      • 多用于参数的传递。
  • 对象.getClass():Object类中定义的方法。
    • Runtime(运行阶段),处于运行时。
      • 用于获取对象的字节码文件对象。
  • Class类对象
    • 同一个字节码文件( .class)在一次程序运行过程中,只会被加载一次。
    • 不论通过哪一种方式获取的Class类对象都是同一个。
      1
      2
      3
      4
      5
      6
      7
      8

      // Class类.静态方法forName("全类名")
      Class class1 = Class.forName("com.test.Person");
      // 类名.成员class
      Class class2 = Person.class;
      // 对象名.成员方法getClass()
      Person person = new Person();
      Class class3 = person.getClass();

获取成员变量

  • Field[] getFields()
    • 返回包含一个 Field对象数组,反射 所有可访问的 public字段类对象。
  • Field getField(String name)
    • 返回一个 Field对象,反射 指定的 public成员字段类对象。
  • Field[] getDeclaredFields()
    • 返回一个 Field对象,反射 所有可访问的 已声明字段类对象。(不考虑修饰符)
  • Field getDeclaredField(String name)
    • 返回一个 Field对象数组,反射 指定已声明字段类对象。(不考虑修饰符)

      Person类中的成员变量

1
2
3
4
5
6
7
8
9
//    public修饰符
public String publicName;
public int publicAge;
// private修饰符
private String privateName;
// protected修饰符
protected String protectedName;
// 无修饰符
String name;

获取Person类中的成员变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Class pc = Person.class;

/* getField("") */
Field fie = pc.getField("publicName");
// public java.lang.String test.Person.publicName

/* getFields() */
Field[] fies = pc.getFields();
// public java.lang.String test.Person.publicName
// public int test.Person.publicAge

/* getDeclaredField("") */
Field fie = pc.getDeclaredField("privateName");
privateName.setAccessible(true);
// private java.lang.String test.Person.privateName


/* getDeclaradFields() */
Field[] fies = pc.getDeclaredFields();
for (Field fie : fies) {
fie.setAccessible(true);
}
// public java.lang.String test.Person.publicName
// private java.lang.String test.Person.privateName
// protected java.lang.String test.Person.protectedName
// java.lang.String test.Person.name

获取构造方法

  • Constructor<?>[] getConstructors()
    • 返回一个 Constructor对象,反射 指定的 public构造类对象。
  • Constructor<T> getDeclaredConstructor(类<?>… parameterTypes)
    • 返回一个 Constructor对象,反射 指定的 构造类对象。
  • Constructor<T> getConstructor(类<?>… parameterTypes)
    • 返回一个 Constructor对象数组,反射 所有的 public构造类对象。
  • Constructor<?>[] getDeclaredConstructors()
    • 返回一个 Constructor对象数组,反射 所有定的 构造类对象。

Person类中的构造方法

1
2
3
4
5
6
7
8
9

// 无参构造
public Person() {}

// public 带参构造(String)
public Person(String publicName) {}

// private 带参构造(String,String)
private Person(String publicName,String privateName) {}

获取Person类中的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

/* getConstructor */
Constructor con = pc.getConstructor();
Object object = constructor.newInstance();
// {publicName='null', privateName='null'}
Constructor con = pc.getConstructor(String.class);
Object object = constructor2.newInstance("Cat");
// {publicName='Cat', privateName='null'}


/* getDeclaredConstructor */
Constructor con = pc.getDeclaredConstructor(String.class,String.class,);
declaredConstructor.setAccessible(true);
Object object = declaredConstructor1.newInstance("Pig","Pug");
// {publicName='Pig', privateName='Pug'}


/* getConstructors */
Constructor[] cons = pc.getConstructors();
// public test.Person()
// public test.Person(java.lang.String,)


/* getDeclaredConstructors */
Constructor[] cons = pc.getDeclaredConstructors();
// public test.Person()
// public test.Person(java.lang.String)
// private test.Person(java.lang.String,java.lang.String)

获取成员方法

  • Method getMethod(String name, 类<?>… parameterTypes)
    • 返回一个 Method对象,反射 指定的 public成员方法类对象。
  • Method getDeclaredMethod(String name, 类<?>… parameterTypes)
    • 返回一个 Method对象,反射 指定的 成员方法类对象。
  • Method[] getMethods()
    • 返回一个 Method对象数组,反射 所有的 public成员方法类对象。
  • Method[] getDeclaredMethods()
    • 返回一个 Method对象数组,反射 所有的 成员方法类对象。

Person类中的成员方法

1
2
3
4
5
6
7
8
9
10

// public修饰符
public void publicMethod111(){System.out.println("publicMethod()...");}
public void publicMethod222(String s){System.out.println("publicMethod("+ s +")...");}

// private修饰符
private void privateMethod(){System.out.println("privateMethod()...");}

// protected修饰符
protected void protectedMethod(){System.out.println("publicMethod()...");}

获取Person类中的成员方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

Class pc = Person.class;
Person p = new Person();

/* getMethod */
Method method = personClass.getMethod("publicMethod111");
// public void test.Person.publicMethod111()
method.invoke(p);
// publicMethod()...
Method method = personClass.getMethod("publicMethod222", String.class);
// public void test.Person.publicMethod222(java.lang.String)
method.invoke(p,"带参");
// publicMethod(带参)...

/* getDeclaredMethod */
Method method = pc.getDeclaredMethod("privateMethod");
//private void test.Person.privateMethod()
method.setAccessible(true);
method.invoke(p);
// privateMethod()...

/* getMethods */
Method[] methods = personClass.getMethods();
//public java.lang.String test.Person.toString()
//public java.lang.String test.Person.getName()
//public void test.Person.setName(java.lang.String)
//public void test.Person.publicMethod111()
//public void test.Person.publicMethod222(java.lang.String)
//public void test.Person.setPublicAge(int)
//public void test.Person.setProtectedName(java.lang.String)
//public int test.Person.getPublicAge()
// ................................

/* getDeclaredMethods */
Method[] methods = personClass.getDeclaredMethods();
// public java.lang.String test.Person.toString()
// public java.lang.String test.Person.getName()
// public void test.Person.setName(java.lang.String)
// public void test.Person.publicMethod111()
// protected void test.Person.protectedMethod()
// private void test.Person.privateMethod()
// public void test.Person.publicMethod222(java.lang.String)
// public void test.Person.setPublicAge(int)
// public void test.Person.setProtectedName(java.lang.String)
// ...............................

获取全类名

  • String getName()

其他操作

操作Field

  • 设置值
    • void set(Object obj, Object value)
  • 获取值
    • get(Object obj)
  • 暴力反射:忽略访问权限修饰符的安全检查
    • setAccessible(true):暴力反射
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18

      Class pc = Person.class;
      Person p = new Person();

      /*public修饰符*/
      Field fie = pc.getField("publicName");
      // public java.lang.String test.Person.publicName
      fie.set(p,"cat");
      System.out.print( fie.get(p) );
      // cat

      /*private修饰符*/
      Field fie = pc.getDeclaredField("privateName");
      // private java.lang.String test.Person.privateName
      pc.setAccessible(true);
      pc.set(p,"dog");
      System.out.print( fie.get(p) );
      // dog

操作Constructor

  • 创建对象
    • T newInstance(Object… initargs)
  • 如果使用空参数构造方法创建对象,操作可以简化
    • Class对象的newInstance方法
1
2
3
4
5
6
7
8
9
10
11
12
 
/* Class */
Class pc = Person.class;
Object object = pc.newInstance();
// {publicName='null', privateName='null'}


/* Constructor */
Class pc = Person.class;
Constructor con = pc.getConstructor();
Object object = constructor.newInstance();
// {publicName='null', privateName='null'}

操作Method

  • 执行方法
    • Object invoke(Object obj, Object… args)
  • 获取方法名
    • String getName
      1
      2
      3
      4
      5
      Class pc = Person.class;
      Person p = new Person();
      Method method = personClass.getMethod("publicMethod111");
      method.invoke(p);
      // publicMethod()...
-------------本文结束-------------
Donate comment here